package com.fount4j.generator.introspect;

import com.fount4j.generator.config.DaoConfig;
import com.fount4j.generator.context.GeneratorContext;
import com.fount4j.generator.exception.GenerateException;
import com.fount4j.generator.info.ColumnInfo;
import com.fount4j.generator.info.DaoInfo;
import com.fount4j.generator.info.EntityInfo;
import com.fount4j.generator.util.BeanUtils;
import com.fount4j.generator.util.GeneratorFileUtils;
import com.fount4j.generator.util.StringUtils;

import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * Dao 类解析器
 *
 * @author Morven 2016/12/22
 */
public class DaoIntrospector implements BaseIntrospector {

    /**
     * 解析 Dao 类
     *
     * @param context 生成器上下文
     */
    @Override
    public void introspect(GeneratorContext context) {
        context.setDaoInfo(new DaoInfo());

        introspectName(context);
        introspectPackage(context);
        introspectFile(context);
        introspectImports(context);
        introspectPrimaryKey(context);
    }

    /**
     * 解析主键相关的属性
     *
     * @param context 生成器上下文
     */
    protected void introspectPrimaryKey(GeneratorContext context) {
        List<ColumnInfo> primaryKeyColumns = context.getTableInfo().getPrimaryKeyColumns();
        if (primaryKeyColumns.isEmpty()) {
            return;
        }
        if (primaryKeyColumns.size() > 1) {
            context.getDaoInfo().setPkJavaType(context.getEntityInfo().getName());
            context.getDaoInfo().setPkJavaTypeReference(context.getEntityInfo().getReference());
        } else {
            ColumnInfo columnInfo = primaryKeyColumns.get(0);
            context.getDaoInfo().setPkJavaType(columnInfo.getJavaTypeName());
            context.getDaoInfo().setPkJavaTypeReference(columnInfo.getJavaType().getName());
        }
    }

    /**
     * 解析 Dao 类文件路径
     *
     * @param context 生成器上下文
     */
    protected void introspectFile(GeneratorContext context) {
        DaoConfig daoConfig = context.getDaoConfig();
        String packageName = context.getTableConfig().getDaoPackage();
        if (StringUtils.isBlank(packageName)) {
            packageName = daoConfig.getPackageName();
        }

        File file = GeneratorFileUtils
                .getFile(daoConfig.getResourcePath(), packageName, context.getDaoInfo().getName() + ".java");
        context.getDaoInfo().setFile(file);
        try {
            context.getDaoInfo().setCustomContent(GeneratorFileUtils.getCustomContent(file));
        } catch (IOException e) {
            throw new GenerateException("读取文件自定义内容出错: " + file, e);
        }
    }

    /**
     * 解析 Dao 类需要导入的包
     *
     * @param context 生成器上下文
     */
    protected void introspectImports(GeneratorContext context) {
        Set<String> imports = new LinkedHashSet<>();
        File file = context.getDaoInfo().getFile();
        try {
            List<String> importList = GeneratorFileUtils.getImports(file);
            imports.addAll(importList);
        } catch (IOException e) {
            throw new GenerateException("读取类 import 内容出错: " + file, e);
        }

        EntityInfo entityInfo = context.getEntityInfo();
        if (!entityInfo.getPackageContent().equals(context.getDaoInfo().getPackageContent())) {
            imports.add(entityInfo.getReference());
        }

        List<String> importsConfig = context.getDaoConfig().getImports();
        if (importsConfig != null) {
            imports.addAll(importsConfig);
        }

        try {
            BeanUtils.removeUnuseImport(file, imports);
        } catch (IOException e) {
            e.printStackTrace();
        }
        List<String> importList = new ArrayList<>(imports);
        context.getDaoInfo().setImports(BeanUtils.createImportsList(importList));
    }

    /**
     * 解析 Dao 类的包路径
     *
     * @param context 生成器上下文
     */
    protected void introspectPackage(GeneratorContext context) {
        String packageContent = context.getTableConfig().getDaoPackage();
        if (StringUtils.isBlank(packageContent)) {
            packageContent = context.getDaoConfig().getPackageName();
        }

        String reference = context.getDaoInfo().getName();
        if (StringUtils.isBlank(packageContent)) {
            packageContent = "";
        } else {
            reference = packageContent + "." + reference;
            packageContent = "package " + packageContent + ";";
        }
        context.getDaoInfo().setPackageContent(packageContent);
        context.getDaoInfo().setReference(reference);
    }

    /**
     * 解析 Dao 类的名称
     *
     * @param context 生成器上下文
     */
    private void introspectName(GeneratorContext context) {
        context.getDaoInfo().setName(context.getEntityInfo().getName() + context.getDaoConfig().getNameSuffix());
    }

}
